﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LumaQQ.NET.Packets.In;
using LumaQQ.NET.Packets;
using LumaQQ.NET.Net;
using LumaQQ.NET.Packets.In._08;
using LumaQQ.NET.Packets.Out._08;
using LumaQQ.NET.Packets.Out;

namespace LumaQQ.NET.Events
{
    public class _08BasicFamilyProcessor : IPacketListener
    {
        QQClient client;
        // QQ用户，我们将在收到登陆包后设置user不为null，所以如果user为null意味着尚未登陆
        QQUser user;
        public _08BasicFamilyProcessor(QQClient client)
        {
            this.client = client;
        }

        public void PacketArrived(Packets._08InPacket inpacket)
        {
            if (inpacket is UnknownInPacket)
            {
                client.PacketManager.OnReceivedUnknownPacket(new QQEventArgs<UnknownInPacket>((UnknownInPacket)inpacket));
                return;
            }
            if (inpacket is ErrorPacket)
            {
                ErrorPacket error = (ErrorPacket)inpacket;
                if (error.ErrorType == ErrorPacketType.ERROR_TIMEOUT)
                {
                    client.PacketManager.OnSendPacketTimeOut(new QQEventArgs<_08OutPacket>(error.TimeOutPacket));
                }
                else
                {
                    client.OnError(new QQEventArgs<ErrorPacket>((ErrorPacket)inpacket));
                }
                return;
            }
            // 检查目前是否已经登录
            if (user == null || !user.IsLoggedIn)
            {
                //按理说应该把在登陆之前时收到的包缓存起来，但是在实际中观察发现，登录之前收到的
                //东西基本没用，所以在这里不做任何事情，简单的抛弃这个包
                if (!IsPreloginPacket(inpacket))
                {
                    return;
                }
            }
            // 现在开始判断包的类型，作出相应的处理
            ConnectionPolicy policy = client.ConnectionManager.GetConnection(inpacket.PortName).Policy;
            // 根据输入包，检索对应的输出包
            _08OutPacket outpacket = policy.RetrieveSent(inpacket);
            // 这里检查是不是服务器发回的确认包
            // 为什么要检查这个呢，因为有些包是服务器主动发出的，对于这些包我们是不需要
            // 从超时发送队列中移除的，如果是服务器的确认包，那么我们就需要把超时发送队列
            // 中包移除
            switch (inpacket.Command)
            {
                // 这三种包是服务器先发出的，我们要确认
                case _08QQ.Command.QQ_CMD_RECV_IM:
                case _08QQ.Command.QQ_CMD_RECV_MSG_SYS:
                case _08QQ.Command.QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
                    break;
                // 未知命令忽略掉
                case _08QQ.Command.QQ_CMD_UNKNOWN:
                    break;
                // 其他情况我们删除超时队列中的包
                default:
                    client.PacketManager.RemoveResendPacket(inpacket);
                    client.PacketManager.OnSentPacketSuccessfully(new QQEventArgs<_08OutPacket, _08InPacket>(outpacket, inpacket));
                    break;
            }
            this.user = client.QQUser;
            switch (inpacket.Command)
            {
                case _08QQ.Command.QQ_CMD_FIRST_LOGIN:
                    ProcessFirstLoginReply((_08FirstLoginPacket)outpacket, (_08FirstLoginReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_LOGOUT:
                    break;
                case _08QQ.Command.QQ_CMD_KEEP_ALIVE:
                    ProcessKeepAliveReply((_08KeepAlivePacket)outpacket, (_08KeepAliveReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_MODIFY_INFO:
                    ProcessModifyInfoReply((_08ModifyInfoPacket)outpacket, (_08ModifyInfoReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_SEARCH_USER:
                    ProcessSearchUserReply((SearchUserPacket)outpacket, (SearchUserReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_GET_USER_INFO:
                    ProcessGetUserInfoReply((GetUserInfoPacket)outpacket, (GetUserInfoReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_DELETE_FRIEND:
                    ProcessDeleteFriendReply((DeleteFriendPacket)outpacket, (DeleteFriendReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_ADD_FRIEND_AUTH:
                    ProcessAddFriendAuthReply((AddFriendAuthResponsePacket)outpacket, (AddFriendAuthResponseReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_CHANGE_STATUS:
                    ProcessChangeStatusReply((ChangeStatusPacket)outpacket, (ChangeStatusReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_ACK_SYS_MSG:

                    break;
                case _08QQ.Command.QQ_CMD_SEND_IM:

                    break;
                case _08QQ.Command.QQ_CMD_RECV_IM:
                    //ProcessInputStatusIM(inPacket);
                    ProcessReceiveIM((ReceiveIMPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_REMOVE_SELF:
                    ProcessRemoveSelfReply((RemoveSelfPacket)outpacket, (RemoveSelfReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_REQUEST_KEY:
                    ProcessRequestKeyReply((GetKeyPacket)outpacket, (GetKeyReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_LOGIN:
                    this.user = client.QQUser;
                    ProcessLoginReply((_08LoginPacket)outpacket, (_08LoginReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_TOUCH:
                    this.user = client.QQUser;
                    ProcessTouchLogin((_08TouchLoginPacket)outpacket, (_08TouchLoginReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_CHECK_PASSWORD:
                    this.user = client.QQUser;
                    ProcessLoginKey((_08LoginKeyPacket)outpacket, (_08LoginKeyReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_LOGIN_TOKEN_1:
                    this.user = client.QQUser;
                    ProcessLoginToken1((_08LoginToken1Packet)outpacket, (_08LoginToken1ReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_LOGIN_TOKEN_2:
                    this.user = client.QQUser;
                    ProcessLoginToken2((_08LoginToken2Packet)outpacket, (_08LoginToken2ReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_SERVERTOKEN:

                    break;
                case _08QQ.Command.QQ_CMD_PROVEPW:
                    break;
                case _08QQ.Command.QQ_CMD_GET_FRIEND_LIST:
                    ProcessGetFriendListReply((GetFriendListPacket)outpacket, (GetFriendListReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_GET_ONLINE_OP:
                    ProcessGetFriendOnlineReply((_08GetOnlineOpPacket)outpacket, (_08GetOnlineOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_SEND_SMS:
                    break;
                case _08QQ.Command.QQ_CMD_CLUSTER_CMD:
                    ProcessClusterCommandReply((ClusterCommandPacket)outpacket, (ClusterCommandReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_TEST:
                    break;
                case _08QQ.Command.QQ_CMD_GROUP_DATA_OP:
                    ProcessGroupNameOpReply((GroupDataOpPacket)outpacket, (GroupDataOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_UPLOAD_GROUP_FRIEND:
                    ProcessUploadGroupFriendReply((UploadGroupFriendPacket)outpacket, (UploadGroupFriendReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_FRIEND_DATA_OP:
                    ProcessFriendDataOpReply((FriendDataOpPacket)outpacket, (FriendDataOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_DOWNLOAD_GROUP_FRIEND:
                    ProcessDownloadGroupFriendReply((DownloadGroupFriendPacket)outpacket, (DownloadGroupFriendReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_FRIEND_LEVEL_OP:
                    ProcessFriendLevelOpReply((FriendLevelOpPacket)outpacket, (FriendLevelOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_PRIVACY_DATA_OP:
                    ProcessPrivacyDataOpReply((PrivacyDataOpPacket)outpacket, (PrivacyDataOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_CLUSTER_DATA_OP:

                    break;
                case _08QQ.Command.QQ_CMD_ADVANCED_SEARCH:
                    ProcessAdvancedSearchReply((AdvancedSearchUserPacket)outpacket, (AdvancedSearchUserReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_USER_PROPERTY_OP:
                    ProcessUserPropertyOpReply((UserPropertyOpPacket)outpacket, (UserPropertyOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_TEMP_SESSION_OP:
                    ProcessTempSessionOpReply((TempSessionOpPacket)outpacket, (TempSessionOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_SIGNATURE_OP:
                    ProcessSignatureOpReply((_08SignatureOpPacket)outpacket, (_08SignatureOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_RECV_MSG_SYS:
                    ProcessSystemNotification((SystemNotificationPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
                    ProcessFriendChangeStatus((FriendChangeStatusPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_WEATHER_OP:
                    ProcessWeatherOpReply((WeatherOpPacket)outpacket, (WeatherOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_ADD_FRIEND_EX:
                    ProcessAddFriendExReply((AddFriendExPacket)outpacket, (AddFriendExReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_AUTHORIZE:
                    ProcessAuthorizeReply((_08AuthorizePacket)outpacket, (_08AuthorizeReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_AUTH_INFO_OP:
                    ProcessAuthInfoOpReply((_08AuthInfoOpPacket)outpacket, (_08AuthInfoOpReplyPacket)inpacket);
                    break;
                case _08QQ.Command.QQ_CMD_AUTH_QUESTION_OP:
                    ProcessAuthQuestionOpReply((AuthQuestionOpPacket)outpacket, (AuthQuestionOpReplyPacket)inpacket);
                    break;
                //case _08QQ.Command.QQ_CMD_GET_LOGIN_TOKEN:
                //    break;
                case _08QQ.Command.QQ_CMD_UNKNOWN:
                    break;
                default:
                    break;
            }
        }

        #region event processor

        #region Login
        /**
     * 处理首次登陆的回复包
     */
        public void ProcessFirstLoginReply(_08FirstLoginPacket outpacket, _08FirstLoginReplyPacket inpacket)
        {
            var e = new QQEventArgs<_08FirstLoginPacket, _08FirstLoginReplyPacket>(outpacket, inpacket);
            client.LoginManager.OnFirstLogin(e);
        }

        private void ProcessTouchLogin(_08TouchLoginPacket outpacket, _08TouchLoginReplyPacket inpacket)
        {
            if (inpacket.ServerIP != null && inpacket.ServerIP.Length > 0)
            {
                // 设置推荐服务器地址，前提是Touch失败,第一次一般都是Touch失败，因为我设定的服务器是随便定的
                if (user != null)
                {
                    if (user.IsUdp)
                    {
                        //log.debug("开始连接推荐服务器--" + Util.getIpStringFromBytes(packet.serverIp));
                        client.LoginManager.SendTouch(
                                Utils.Util.GetIpStringFromBytes(inpacket.ServerIP), _08QQ.QQ_PORT_UDP);
                        user.SuggestServerIp = inpacket.ServerIP;
                        return;
                    }
                    else
                    {
                        //log.debug("开始连接推荐服务器--" + Util.getIpStringFromBytes((packet.serverIp)));
                        client.LoginManager.SendTouch(
                                Utils.Util.GetIpStringFromBytes(inpacket.ServerIP), 80);
                        user.SuggestServerIp = inpacket.ServerIP;
                        return;
                    }
                }
            }
            var e = new QQEventArgs<_08TouchLoginPacket, _08TouchLoginReplyPacket>(outpacket, inpacket);

            client.LoginManager.OnSentTouchSuccessfully(e);

        }

        /// <summary>
        /// 处理登陆令牌1
        /// </summary>
        /// <param name="outpacket">The outpacket.</param>
        /// <param name="inpacket">The inpacket.</param>
        /// 处理登陆令牌1
        /// @param in
        /// @author seraph
        private void ProcessLoginToken1(_08LoginToken1Packet outpacket, _08LoginToken1ReplyPacket inpacket)
        {


            if (inpacket.LoginToken1 != null)
            {
                user.LoginToken = inpacket.LoginToken1;
            }
            var e = new QQEventArgs<_08LoginToken1Packet, _08LoginToken1ReplyPacket>(outpacket, inpacket);

            client.LoginManager.OnGetLoginToken1Successfully(e);
        }

        /// <summary>
        /// 处理登陆令牌2
        /// </summary>
        /// <param name="inpacket">The inpacket.</param>
        /// 处理登陆令牌2
        /// @param in
        /// @author luna 
        private void ProcessLoginToken2(_08LoginToken2Packet outpacket, _08LoginToken2ReplyPacket inpacket)
        {
            var e = new QQEventArgs<_08LoginToken2Packet, _08LoginToken2ReplyPacket>(outpacket, inpacket);
            switch (inpacket.ReplyCode)
            {
                case _08QQ.Reply_LoginToken2.QQ_REPLY_OK:
                    //log.debug("得到登录令牌成功");
                    user.TempToken = inpacket.LoginToken2;

                    client.LoginManager.OnGetLoginToken2Successfully(e);
                    break;
                case _08QQ.Reply_LoginToken2.QQ_REPLY_LOGIN_NEED_VERIFY:
                    //log.debug("需要输入验证码");
                    user.TempToken = inpacket.LoginToken2;
                    user.PuzzleToken = inpacket.NextImageToken;


                    client.LoginManager.OnNeedVerifyCode(e);

                    break;
            }
        }

        /// <summary>
        /// Processes the login key.
        /// </summary>
        /// <param name="outpacket">The outpacket.</param>
        /// <param name="inpacket">The inpacket.</param>
        /// 处理登陆密匙
        /// @param in
        /// @author luna

        private void ProcessLoginKey(_08LoginKeyPacket outpacket, _08LoginKeyReplyPacket inpacket)
        {

            var e = new QQEventArgs<_08LoginKeyPacket, _08LoginKeyReplyPacket>(outpacket, inpacket);
            switch (inpacket.ReplyCode)
            {
                case _08QQ.Reply_LoginKey.QQ_REPLY_OK:
                    user.LoginKey = inpacket.Key;
                    user.LoginToken = inpacket.LoginToken;
                    this.client.LoginManager.OnPasswordChecked(e);
                    break;
                case _08QQ.Reply_LoginKey.QQ_CMD_PASSWORD_ERROR:
                case _08QQ.Reply_LoginKey.QQ_CMD_NEED_ACTIVATE:
                    //  log.info("用户名或密码错误");
                    this.client.LoginManager.OnPasswordError(e);
                    break;
                default:
                    this.client.LoginManager.OnCheckPasswordFailed(e);
                    break;
            }

        }

        // 处理登陆应答
        private void ProcessLoginReply(_08LoginPacket outpacket, _08LoginReplyPacket inpacket)
        {
            var e = new QQEventArgs<_08LoginPacket, _08LoginReplyPacket>(outpacket, inpacket);
            // 开始判断应答内容
            switch (inpacket.ReplyCode)
            {
                case _08QQ.Reply_Login.QQ_REPLY_OK:
                    //log.debug("登陆成功，用户IP为: " + Util.getIpStringFromBytes(packet.ip) + " 端口: " + packet.port);
                    // 登陆成功的话我们就设置用户的一些信息，然后触发事件
                    user.SessionKey = inpacket.SessionKey;
                    user.IP = inpacket.IP;
                    user.Port = inpacket.Port;
                    user.ServerPort = inpacket.ServerPort;
                    user.LoginTimeRude = inpacket.LoginTimeRude;
                    user.LoginTime = inpacket.LoginTime;
                    user.LastLoginIp = inpacket.LastLoginIP;
                    user.LastLoginTime = inpacket.LastLoginTime;
                    user.ClientKey = inpacket.ClientKey;
                    user.AuthToken = inpacket.AuthToken;
                    user.UserQQ = inpacket.UserQQ;
                    user.ServerIp = inpacket.ServerIP;
                    // 得到文件传输密钥
                    byte[] b = new byte[4 + _08QQ.QQ_LENGTH_KEY];
                    b[0] = (byte)((user.QQ >> 24) & 0xFF);
                    b[1] = (byte)((user.QQ >> 16) & 0xFF);
                    b[2] = (byte)((user.QQ >> 8) & 0xFF);
                    b[3] = (byte)(user.QQ & 0xFF);
                    Array.Copy(user.SessionKey, 0, b, 4, _08QQ.QQ_LENGTH_KEY);
                    user.FileSessionKey = (Utils.Crypter.MD5(b));
                    // 触发事件
                    client.LoginManager.OnLoginSuccessfully(e);
                    break;
                case _08QQ.Reply_Login.QQ_REPLY_LOGIN_FAIL:
                    // log.debug("登录失败: " + packet.replyMessage);
                    // 如果是密码错误，触发事件
                    client.LoginManager.OnLoginFailed(e);
                    break;
                case _08QQ.Reply_Login.QQ_REPLY_LOGIN_REDIRECT:
                    //log.debug("登陆重定向");
                    if (Utils.Util.IsIPZero(inpacket.RedirectIP))
                    {
                        //log.debug("地址重定向到0，随机选取其他服务器再登录");
                        client.LoginManager.OnLoginRedirect(e);
                    }
                    else
                    {
                        // 如果是登陆重定向，继续登陆
                        client.LoginRedirect = true;
                        try
                        {// changed by luna ，以前这里是login(server,port);

                            //log.debug("重定向IP为：" + Util.getIpStringFromBytes(packet.redirectIp));
                            client.LoginManager.SendTouch(Utils.Util.GetIpStringFromBytes(inpacket.RedirectIP),
                                    inpacket.RedirectPort);
                        }
                        catch (Exception e1)
                        {
                            //log.error(e1.getMessage())
                            client.OnException(e1);
                        }
                    }
                    break;
                case _08QQ.Reply_Login.QQ_LOGIN_FAIL://登录失败

                    //log.debug("登录失败，继续登录");
                    try
                    {
                        String suggestIP = null;
                        if (user.SuggestServerIp != null)
                        {
                            suggestIP = Utils.Util.GetIpStringFromBytes(user.SuggestServerIp);
                        }
                        if (suggestIP != null)
                        {
                            if (user.IsUdp)
                            {
                                client.LoginManager.SendTouch(suggestIP, 8000);
                            }
                            else
                            {
                                client.LoginManager.SendTouch(suggestIP, 80);
                            }
                        }
                        else
                        {
                            client.LoginManager.SendTouch();
                        }
                    }
                    catch (Exception e1)
                    {
                        client.OnException(e1);
                    }
                    break;
                //case _08QQ.QQ_CMD_PASSWORD_ERROR:
                //    e = new _08QQEvent(packet);
                //    e.type = _08QQEvent.PASSWORD_ERROR;
                //    break;
                default:
                    //log.debug("未知登陆错误");
                    // 如果是其他未知错误，触发事件
                    client.LoginManager.OnLoginUnknowError(e);
                    break;
            }
        }

        /// <summary>
        /// 处理未知命令，没有实际操作，简单打印内容
        /// </summary>
        /// <param name="outpacket">The outpacket.</param>
        /// <param name="inpacket">The inpacket.</param>
        /// @param in
        /// @deprecated 处理未知命令，没有实际操作，简单打印内容
        private void ProcessRequestKeyReply(GetKeyPacket outpacket, GetKeyReplyPacket inpacket)
        {
            var e = new QQEventArgs<GetKeyPacket, GetKeyReplyPacket>(outpacket, inpacket);
            if (inpacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.LoginManager.OnRequestKeySuccessfully(e);
            }
            else
            {
                client.LoginManager.OnRequestKeyFailed(e);
            }
        }

        #endregion
        /**
     * 处理Keep Alive的回复事件
     *
     * @param in
     */
        private void ProcessKeepAliveReply(_08KeepAlivePacket outpacket, _08KeepAliveReplyPacket inpacket)
        {
            //_08QQEvent e;
            //_08KeepAliveReplyPacket packet = (_08KeepAliveReplyPacket) in;
            var e = new QQEventArgs<_08KeepAlivePacket, _08KeepAliveReplyPacket>(outpacket, inpacket);
            //if (log.isDebugEnabled()) {
            //    log.debug("Keep Alive: 在线数: " + packet.onlines + "我的IP: " + Util.convertIpToString(packet.ip));
            //}

            // 触发事件
            if (inpacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.LoginManager.OnReceivedKeepAlive(e);
            }
        }
        //private void ProcessInputStatusIM(_08InPacket inpacket)
        //{

        //    if (inpacket is _08InputStatusPacket)
        //    {
        //        var packet = (_08InputStatusPacket)inpacket;
        //        var e = new QQEventArgs<_08InputStatusPacket>(packet);
        //        if (packet.Flag != 0)
        //        {
        //            //log.info("用户正在输入信息");
        //            client.MessageManager.OnUserInputingStatus(e);
        //        }
        //    }
        //}
        /// <summary>
        /// 处理接收信息
        /// 	<remark>abu 2008-03-10 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessReceiveIM(ReceiveIMPacket packet)
        {
            var e = new QQEventArgs<ReceiveIMPacket>(packet);
            //先发送接收确认
            client.MessageManager.SendReceiveReplyPacket(packet);
            if (packet.IsDuplicated)
            {
                client.MessageManager.OnReceivedDuplicatedIM(e);
                return;
            }
            if (packet.Flag != 0)
            {
                //log.debug("用户正在输入信息");
                client.MessageManager.OnUserInputingStatus(e);
                return;
            }
            switch (packet.Header.Type)
            {
                case _08QQ.Recv_IMType.QQ_RECV_IM_FRIEND:
                case _08QQ.Recv_IMType.QQ_RECV_IM_STRANGER:
                case _08QQ.Recv_IMType.QQ_RECV_IM_FRIEND_EX:
                    switch (packet.NormalHeader.Type)
                    {
                        case _08QQ.IMType.QQ_IM_TYPE_TEXT:
                            client.MessageManager.OnReceiveNormalIM(e);
                            break;
                        case _08QQ.IMType.QQ_IM_TYPE_UDP_REQUEST:
                            //log.debug("一个尚待处理的命令");
                            break;
                        case _08QQ.IMType.QQ_IM_TYPE_REJECT_UDP_REQUEST:
                            //log.debug("对方拒绝了传送文件的请求");
                            break;
                        case _08QQ.IMType.QQ_IM_TYPE_ACCEPT_UDP_REQUEST:
                            //log.debug("对方接受了传送文件的请求");
                            break;
                        case _08QQ.IMType.QQ_IM_TYPE_NOTIFY_IP:
                            //log.debug("对方告诉我文件发送的IP和端口，其外部IP为" + Util.getIpStringFromBytes(packet.fileArgs.internetIp) + " 其外部端口为" + packet.fileArgs.internetPort + " 其主端口为" + packet.fileArgs.majorPort + " 其真实IP为" + Util.getIpStringFromBytes(packet.fileArgs.localIp) + " 其副端口为" + packet.fileArgs.minorPort);
                            break;
                        case _08QQ.IMType.QQ_IM_TYPE_ARE_YOU_BEHIND_FIREWALL:
                            //log.debug("对方请求自己主动连接他");
                            break;
                        case _08QQ.IMType.QQ_IM_TYPE_REQUEST_CANCELED:
                            //log.debug("对方取消了文件传送");
                            break;

                        default:
                            client.MessageManager.OnReceivedUnknownIM(e);
                            break;
                    }
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_SYS_MESSAGE:
                    //log.debug("接收到一条系统消息: " + packet.sysMessage);
                    if (packet.SystemMessageType == _08QQ.Recv_IMType.QQ_RECV_IM_KICK_OUT)
                    {
                        client.MessageManager.OnReceivedKickOut(e);
                    }
                    else
                    {
                        client.MessageManager.OnReceivedSysMessage(e);
                    }
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_PROPERTY_CHANGE:
                    //todo: QQ_RECV_IM_PROPERTY_CHANGE
                    client.FriendManager.OnUserPropertyChanged(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_TEMP_SESSION:
                    client.MessageManager.OnReceiveTempSessionIM(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_UNKNOWN_CLUSTER:
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_CREATE_CLUSTER:
                case _08QQ.Recv_IMType.QQ_RECV_IM_ADDED_TO_CLUSTER:
                    //todo: QQ_RECV_IM_CREATE_CLUSTER
                    //client.ClusterManager.OnAddedToCluster(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_DELETED_FROM_CLUSTER:
                    //client.ClusterManager.OnRemovedFromCluster(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_REQUEST_JOIN_CLUSTER:
                    //client.ClusterManager.OnHasRequestJoinCluster(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_APPROVE_JOIN_CLUSTER:
                    //client.ClusterManager.OnApprovedJoinCluster(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_REJECT_JOIN_CLUSTER:
                    //client.ClusterManager.OnRejectJoinCluster(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_TEMP_CLUSTER:
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_CLUSTER:
                    //client.ClusterManager.OnReceiveClusterIM(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_CLUSTER_NOTIFICATION:
                    break;

                case _08QQ.Recv_IMType.QQ_RECV_IM_SIGNATURE_CHANGE:
                    client.FriendManager.OnSignatureChanged(e);
                    break;
                case _08QQ.Recv_IMType.QQ_RECV_IM_CUSTOM_HEAD_CHANGE:
                    break;
                default:
                    break;
            }
        }



        /// <summary>
        /// 处理得到好友列表应答
        /// 	<remark>abu 2008-03-11 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessGetFriendListReply(GetFriendListPacket outPacket, GetFriendListReplyPacket inPacket)
        {
            client.FriendManager.OnGetFriendListSuccessfully(new QQEventArgs<GetFriendListPacket, GetFriendListReplyPacket>(outPacket, inPacket));
        }

        /// <summary>
        /// 处理得到在线好友应答
        /// 	<remark>abu 2008-03-11 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessGetFriendOnlineReply(_08GetOnlineOpPacket outPacket, _08GetOnlineOpReplyPacket inPacket)
        {
            client.FriendManager.OnGetOnlineFriendSuccessfully(new QQEventArgs<_08GetOnlineOpPacket, _08GetOnlineOpReplyPacket>(outPacket, inPacket));
        }

        private void ProcessGetUserInfoReply(GetUserInfoPacket outPacket, GetUserInfoReplyPacket inPacket)
        {
            client.FriendManager.OnGetUserInfoSuccessfully(new QQEventArgs<GetUserInfoPacket, GetUserInfoReplyPacket>(outPacket, inPacket));
        }

        /// <summary>处理改变状态回复事件
        /// 	<remark>abu 2008-03-12 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessChangeStatusReply(ChangeStatusPacket outPacket, ChangeStatusReplyPacket inPacket)
        {
            var e = new QQEventArgs<ChangeStatusPacket, ChangeStatusReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.Reply_ChangeStatus.QQ_REPLY_CHANGE_STATUS_OK)
            {
                client.FriendManager.OnChangeStatusSuccessfully(e);
            }
            else
            {
                client.FriendManager.OnChangeStatusFailed(e);
            }
        }

        /// <summary>处理好友状态改变事件
        /// 	<remark>abu 2008-03-12 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessFriendChangeStatus(FriendChangeStatusPacket packet)
        {
            QQEventArgs<FriendChangeStatusPacket> e = new QQEventArgs<FriendChangeStatusPacket>(packet);
            client.FriendManager.OnFriendChangeStatus(e);
        }

        /// <summary>
        /// 处理系统消息，比如谁谁谁添加你为好友
        /// 	<remark>abu 2008-03-12 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessSystemNotification(SystemNotificationPacket packet)
        {
            QQEventArgs<SystemNotificationPacket> e = new QQEventArgs<SystemNotificationPacket>(packet);
            switch (packet.Type)
            {
                case _08QQ.Sys_Msg.QQ_SYS_BEING_ADDED:
                    client.MessageManager.OnSysAddedByOthers(e);
                    break;
                case _08QQ.Sys_Msg.QQ_SYS_ADD_FRIEND_REQUEST:
                    client.MessageManager.OnSysRequestAddMe(e);
                    break;
                case _08QQ.Sys_Msg.QQ_SYS_ADD_FRIEND_APPROVED:
                    client.MessageManager.OnSysAddOtherApproved(e);
                    break;
                case _08QQ.Sys_Msg.QQ_SYS_ADD_FRIEND_REJECTED:
                    client.MessageManager.OnSysAddOtherRejected(e);
                    break;
                case _08QQ.Sys_Msg.QQ_SYS_ADVERTISEMENT:
                    client.MessageManager.OnSysAdvertisment(e);
                    break;
                case _08QQ.Sys_Msg.QQ_SYS_BEING_ADDED_EX:
                    client.MessageManager.OnAddedByOthersEx(e);
                    break;
                case _08QQ.Sys_Msg.QQ_SYS_ADD_FRIEND_REQUEST_EX:
                    client.MessageManager.OnSysRequestAddMeEx(e);
                    break;
                case _08QQ.Sys_Msg.QQ_SYS_ADD_FRIEND_APPROVED_AND_ADD:
                    client.MessageManager.OnSysApprovedAddOtherAndAddMe(e);
                    break;
                case _08QQ.Sys_Msg.QQ_SYS_UPDATE_HINT:
                default:
                    break;
            }
        }

        /// <summary>处理请求加一个好友的回复包
        /// 	<remark>abu 2008-03-12 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessAddFriendExReply(AddFriendExPacket outPacket, AddFriendExReplyPacket inPacket)
        {
            var e = new QQEventArgs<AddFriendExPacket, AddFriendExReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.Reply_AddFriend.QQ_REPLY_OK)
            {
                switch (inPacket.AuthCode)
                {
                    case _08QQ.AuthType.QQ_AUTH_NO:
                        client.FriendManager.OnAddFriendSuccessfully(e);
                        break;
                    case _08QQ.AuthType.QQ_AUTH_NEED:
                        client.FriendManager.OnAddFriendNeedAuth(e);
                        break;
                    case _08QQ.AuthType.QQ_AUTH_REJECT:
                        client.FriendManager.OnAddFriendDenied(e);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                if (inPacket.ReplyCode == _08QQ.Reply_AddFriend.QQ_REPLY_ADD_FRIEND_ALREADY)
                {
                    client.FriendManager.OnFriendAlready(e);
                }
                else
                {
                    client.FriendManager.OnAddFriendFailed(e);
                }
            }
        }

        /// <summary> 处理认证信息的回复包
        /// 	<remark>abu 2008-03-12 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessAddFriendAuthReply(AddFriendAuthResponsePacket outPacket, AddFriendAuthResponseReplyPacket inPacket)
        {
            var e = new QQEventArgs<AddFriendAuthResponsePacket, AddFriendAuthResponseReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode != _08QQ.Reply_AddFriend.QQ_REPLY_ADD_FRIEND_AUTH_OK)
            {
                client.FriendManager.OnResponseAuthFailed(e);
            }
            else
            {
                client.FriendManager.OnResponseAuthSuccessfully(e);
            }
        }

        /// <summary>处理删除自己的回复包
        /// 	<remark>abu 2008-03-12 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessRemoveSelfReply(RemoveSelfPacket outPacket, RemoveSelfReplyPacket inPacket)
        {
            var e = new QQEventArgs<RemoveSelfPacket, RemoveSelfReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.FriendManager.OnRemoveSelfSuccessfully(e);
            }
            else
            {
                client.FriendManager.OnRemoveSelfFailed(e);
            }
        }

        /// <summary>处理删除好友的回复包
        /// 	<remark>abu 2008-03-12 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessDeleteFriendReply(DeleteFriendPacket outPacket, DeleteFriendReplyPacket inPacket)
        {
            var e = new QQEventArgs<DeleteFriendPacket, DeleteFriendReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode != _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.FriendManager.OnDeleteFriendFailed(e);
            }
            else
            {
                client.FriendManager.OnDeleteFriendSuccessfully(e);
            }
        }

        /// <summary>处理认证消息发送包
        /// 	<remark>abu 2008-03-12 </remark>
        /// </summary>
        /// <param name="packet">The packet.</param>
        private void ProcessAuthorizeReply(_08AuthorizePacket outPacket, _08AuthorizeReplyPacket inPacket)
        {
            var e = new QQEventArgs<_08AuthorizePacket, _08AuthorizeReplyPacket>(outPacket, inPacket);
            switch (inPacket.ReplyCode)
            {
                case _08QQ.ReplyCode.QQ_REPLY_OK:
                    client.FriendManager.OnSendAuthSuccessfully(e);
                    break;
                default:
                    client.FriendManager.OnSendAuthFailed(e);
                    break;
            }
        }

        /// <summary>
        /// Processes the upload group friend reply.处理上传分组好友列表回复包
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessUploadGroupFriendReply(UploadGroupFriendPacket outPacket, UploadGroupFriendReplyPacket inPacket)
        {
            var e = new QQEventArgs<UploadGroupFriendPacket, UploadGroupFriendReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.FriendManager.OnUploadGroupFriendSuccessfully(e);
            }
            else
            {
                client.FriendManager.OnUploadGroupFriendFailed(e);
            }
        }

        /// <summary>处理修改个人信息的回复包
        /// Processes the modify info reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessModifyInfoReply(_08ModifyInfoPacket outPacket, _08ModifyInfoReplyPacket inPacket)
        {
            var e = new QQEventArgs<_08ModifyInfoPacket, _08ModifyInfoReplyPacket>(outPacket, inPacket);
            if (inPacket.Success)
            {
                client.PrivacyManager.OnModifyInfoSuccessfully(e);
            }
            else
            {
                client.PrivacyManager.OnModifyInfoFailed(e);
            }
        }

        /// <summary>处理个性签名操作回复包
        /// Processes the signature op reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessSignatureOpReply(_08SignatureOpPacket outPacket, _08SignatureOpReplyPacket inPacket)
        {
            var e = new QQEventArgs<_08SignatureOpPacket, _08SignatureOpReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                switch (inPacket.SubCommand)
                {
                    case _08QQ.SubCMD_Signature.QQ_SUB_CMD_MODIFY_SIGNATURE:
                        client.PrivacyManager.OnModifySignatureSuccessfully(e);
                        break;
                    case _08QQ.SubCMD_Signature.QQ_SUB_CMD_DELETE_SIGNATURE:
                        client.PrivacyManager.OnDeleteSignatureSuccessfully(e);
                        break;
                    case _08QQ.SubCMD_Signature.QQ_SUB_CMD_GET_SIGNATURE:
                        client.PrivacyManager.OnGetSignatureSuccessfully(e);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                switch (inPacket.SubCommand)
                {
                    case _08QQ.SubCMD_Signature.QQ_SUB_CMD_MODIFY_SIGNATURE:
                        client.PrivacyManager.OnModifySignatureFailed(e);
                        break;
                    case _08QQ.SubCMD_Signature.QQ_SUB_CMD_DELETE_SIGNATURE:
                        client.PrivacyManager.OnDeleteSignatureFailed(e);
                        break;
                    case _08QQ.SubCMD_Signature.QQ_SUB_CMD_GET_SIGNATURE:
                        client.PrivacyManager.OnGetSignatureFailed(e);
                        break;
                    default:
                        break;
                }
            }
        }

        /// <summary>处理隐私选项操作回复包
        /// Processes the privacy data op reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessPrivacyDataOpReply(PrivacyDataOpPacket outPacket, PrivacyDataOpReplyPacket inPacket)
        {
            var e = new QQEventArgs<PrivacyDataOpPacket, PrivacyDataOpReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                switch (inPacket.SubCommand)
                {
                    case _08QQ.SubCMD_Privacy.QQ_SUB_CMD_SEARCH_ME_BY_QQ_ONLY:
                        client.PrivacyManager.OnSetSearchMeByQQOnlySuccessfully(e);
                        break;
                    case _08QQ.SubCMD_Privacy.QQ_SUB_CMD_SHARE_GEOGRAPHY:
                        client.PrivacyManager.OnSetShareGeographySuccessfully(e);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                switch (inPacket.SubCommand)
                {
                    case _08QQ.SubCMD_Privacy.QQ_SUB_CMD_SEARCH_ME_BY_QQ_ONLY:
                        client.PrivacyManager.OnSetSearchMeByQQOnlyFailed(e);
                        break;
                    case _08QQ.SubCMD_Privacy.QQ_SUB_CMD_SHARE_GEOGRAPHY:
                        client.PrivacyManager.OnSetShareGeographyFailed(e);
                        break;
                    default:
                        break;
                }
            }
        }

        /// <summary>处理上传下载备注的回复包
        /// Processes the friend data op reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessFriendDataOpReply(FriendDataOpPacket outPacket, FriendDataOpReplyPacket inPacket)
        {
            var e = new QQEventArgs<FriendDataOpPacket, FriendDataOpReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                switch (inPacket.SubCommand)
                {
                    case _08QQ.SubCMD_Friend_OP.QQ_SUB_CMD_BATCH_DOWNLOAD_FRIEND_REMARK:
                        client.FriendManager.OnBatchDownloadFriendRemarkSuccessfully(e);
                        break;
                    case _08QQ.SubCMD_Friend_OP.QQ_SUB_CMD_UPLOAD_FRIEND_REMARK:
                        client.FriendManager.OnUploadFriendRemarkSuccessfully(e);
                        break;
                    case _08QQ.SubCMD_Friend_OP.QQ_SUB_CMD_REMOVE_FRIEND_FROM_LIST:
                        client.FriendManager.OnRemoveFriendFromListSuccessfully(e);
                        break;
                    case _08QQ.SubCMD_Friend_OP.QQ_SUB_CMD_DOWNLOAD_FRIEND_REMARK:
                        client.FriendManager.OnDownloadFriendRemarkSuccessfully(e);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                switch (inPacket.SubCommand)
                {
                    case _08QQ.SubCMD_Friend_OP.QQ_SUB_CMD_BATCH_DOWNLOAD_FRIEND_REMARK:
                        client.FriendManager.OnBatchDownloadFriendRemarkFailed(e);
                        break;
                    case _08QQ.SubCMD_Friend_OP.QQ_SUB_CMD_UPLOAD_FRIEND_REMARK:
                        client.FriendManager.OnUploadFriendRemarkFailed(e);
                        break;
                    case _08QQ.SubCMD_Friend_OP.QQ_SUB_CMD_REMOVE_FRIEND_FROM_LIST:
                        client.FriendManager.OnRemoveFriendFromListFailed(e);
                        break;
                    case _08QQ.SubCMD_Friend_OP.QQ_SUB_CMD_DOWNLOAD_FRIEND_REMARK:
                        client.FriendManager.OnDownloadFriendRemarkFailed(e);
                        break;
                    default:
                        break;
                }
            }
        }

        /// <summary>处理好友等级回复包
        /// Processes the friend level op reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessFriendLevelOpReply(FriendLevelOpPacket outPacket, FriendLevelOpReplyPacket inPacket)
        {
            var e = new QQEventArgs<FriendLevelOpPacket, FriendLevelOpReplyPacket>(outPacket, inPacket);
            client.FriendManager.OnGetFriendLevelSuccessfully(e);
        }

        /// <summary>处理用户属性回复包
        /// Pocesses the user property op reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void PocessUserPropertyOpReply(UserPropertyOpPacket outPacket, UserPropertyOpReplyPacket inPacket)
        {
            var e = new QQEventArgs<UserPropertyOpPacket, UserPropertyOpReplyPacket>(outPacket, inPacket);
            client.FriendManager.OnGetUserPropertySuccess(e);
        }

        /// <summary>处理下载分组好友列表回复包
        /// Processes the download group friend reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessDownloadGroupFriendReply(DownloadGroupFriendPacket outPacket, DownloadGroupFriendReplyPacket inPacket)
        {
            var e = new QQEventArgs<DownloadGroupFriendPacket, DownloadGroupFriendReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.FriendManager.OnDownloadGroupFriendSuccessfully(e);
            }
            else
            {
                client.FriendManager.OnDownloadGroupFriendFailed(e);
            }
        }

        /// <summary>处理分组名称回复包
        /// Processes the group name op reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessGroupNameOpReply(GroupDataOpPacket outPacket, GroupDataOpReplyPacket inPacket)
        {
            var e = new QQEventArgs<GroupDataOpPacket, GroupDataOpReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                switch (inPacket.SubCommand)
                {
                    case _08QQ.SubCMD_Group.QQ_SUB_CMD_DOWNLOAD_GROUP_NAME:
                        client.FriendManager.OnDownloadGroupNamesSuccessfully(e);
                        break;
                    case _08QQ.SubCMD_Group.QQ_SUB_CMD_UPLOAD_GROUP_NAME:
                        client.FriendManager.OnUploadGroupNamesSuccessfully(e);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                switch (inPacket.SubCommand)
                {
                    case _08QQ.SubCMD_Group.QQ_SUB_CMD_DOWNLOAD_GROUP_NAME:
                        client.FriendManager.OnDownloadGroupNamesFailed(e);
                        break;
                    case _08QQ.SubCMD_Group.QQ_SUB_CMD_UPLOAD_GROUP_NAME:
                        client.FriendManager.OnUploadGroupNamesFailed(e);
                        break;
                    default:
                        break;
                }
            }
        }

        /// <summary>处理搜索用户的回复包
        /// Processes the search user reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessSearchUserReply(SearchUserPacket outPacket, SearchUserReplyPacket inPacket)
        {
            var e = new QQEventArgs<SearchUserPacket, SearchUserReplyPacket>(outPacket, inPacket);
            client.FriendManager.OnSearchUserSuccessfully(e);
        }
        /**
    * 处理天气预报操作回复包
    *
    * @param in
    */
        private void ProcessWeatherOpReply(WeatherOpPacket outpackt, WeatherOpReplyPacket inpacket)
        {
            var e = new QQEventArgs<WeatherOpPacket, WeatherOpReplyPacket>(outpackt, inpacket);
            switch (inpacket.ReplyCode)
            {
                case _08QQ.ReplyCode.QQ_REPLY_OK:
                    client.PrivacyManager.OnGetWeatherSuccessfully(e);
                    break;
                default:
                    client.PrivacyManager.OnGetWeatherFailed(e);
                    break;
            }
        }

        /// <summary>处理群命令回复包
        /// Processes the cluster command reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterCommandReply(ClusterCommandPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            switch (inPacket.SubCommand)
            {
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_CREATE_CLUSTER:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_MODIFY_MEMBER:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_MODIFY_CLUSTER_INFO:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_GET_CLUSTER_INFO:
                    ProcessClusterGetInfoReply((ClusterGetInfoPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_ACTIVATE_CLUSTER:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_SEARCH_CLUSTER:
                    ProcessClusterSearchReply((ClusterSearchPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_JOIN_CLUSTER:
                    ProcessClusterJoinReply((ClusterJoinPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_JOIN_CLUSTER_AUTH:
                    ProcessClusterJoinAuthReply((ClusterAuthPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_EXIT_CLUSTER:
                    ProcessClusterExitReply((ClusterExitPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_GET_ONLINE_MEMBER:
                    ProcessClusterGetOnlineMemberReply((ClusterGetOnlineMemberPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_GET_MEMBER_INFO:
                    ProccessClusterGetMemberInfoReply((ClusterGetMemberInfoPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_MODIFY_CARD:
                    ProcessModifyCardReply((ClusterModifyCardPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_GET_CARD_BATCH:
                    ProcessClusterGetCardBatchReply((ClusterGetCardBatchPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_GET_CARD:
                    ProcessClusterGetCardReply((ClusterGetCardPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_COMMIT_ORGANIZATION:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_UPDATE_ORGANIZATION:
                    ProcessUpdateOrganizationReply((ClusterUpdateOrganizationPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_COMMIT_MEMBER_ORGANIZATION:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_GET_VERSION_ID:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_SEND_IM_EX:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_SET_ROLE:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_TRANSFER_ROLE:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_DISMISS_CLUSTER:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_CREATE_TEMP:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_MODIFY_TEMP_MEMBER:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_EXIT_TEMP:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_GET_TEMP_INFO:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_MODIFY_TEMP_INFO:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_SEND_TEMP_IM:
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_SUB_CLUSTER_OP:
                    ProcessClusterSubClusterOpReply((ClusterSubClusterOpPacket)outPacket, inPacket);
                    break;
                case _08QQ.ClusterCommand.QQ_CLUSTER_CMD_ACTIVATE_TEMP:
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// Processes the cluster join reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterJoinReply(ClusterJoinPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterJoinPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                switch (inPacket.JoinReply)
                {
                    case _08QQ.Cluster_JoinResult.QQ_CLUSTER_JOIN_OK:
                        client.ClusterManager.OnClusterJoinSuccessfully(e);
                        break;
                    case _08QQ.Cluster_JoinResult.QQ_CLUSTER_JOIN_NEED_AUTH:
                        client.ClusterManager.OnJoinClusterNeedAuth(e);
                        break;
                    case _08QQ.Cluster_JoinResult.QQ_CLUSTER_JOIN_DENIED:
                        client.ClusterManager.OnJoinClusterDenied(e);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                client.ClusterManager.OnJoinClusterFailed(e);
            }
        }
        /// <summary>处理认证信息发送的回复包
        /// Processes the cluster join auth reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterJoinAuthReply(ClusterAuthPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterAuthPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnSendJoinClusterAuthSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnSendJoinClusterAuthFailed(e);
            }
        }
        /// <summary>
        /// Processes the cluster search reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterSearchReply(ClusterSearchPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterSearchPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnSearchClusterSuccessfully(e);
            }
            else
                client.ClusterManager.OnSearchClusterFailed(e);
        }
        /// <summary>
        /// Processes the cluster exit reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterExitReply(ClusterExitPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterExitPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnExitClusterSuccessfully(e);
            }
            else
                client.ClusterManager.OnExitClusterFailed(e);
        }
        /// <summary>
        /// Processes the cluster send IM ex reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterSendIMExReply(ClusterSendIMExPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterSendIMExPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnSendClusterIMExSuccessfully(e);
            }
            else
                client.ClusterManager.OnSendClusterIMExFailed(e);
        }

        /// <summary>
        /// Processes the modify card reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessModifyCardReply(ClusterModifyCardPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterModifyCardPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnModifyCardSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnModifyCardFailed(e);
            }
        }

        /// <summary>
        /// Processes the update organization reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessUpdateOrganizationReply(ClusterUpdateOrganizationPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterUpdateOrganizationPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnUpdateOrganizationSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnUpdateOrganizationFailed(e);
            }
        }

        /// <summary>
        /// Processes the cluster get online member reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterGetOnlineMemberReply(ClusterGetOnlineMemberPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterGetOnlineMemberPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnGetOnlineMemberSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnGetOnlineMemberFailed(e);
            }
        }
        /// <summary>
        /// Processes the cluster get info reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterGetInfoReply(ClusterGetInfoPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterGetInfoPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnGetClusterInfoSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnGetClusterInfoFailed(e);
            }
        }
        /// <summary>
        /// Proccesses the cluster get member info reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProccessClusterGetMemberInfoReply(ClusterGetMemberInfoPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterGetMemberInfoPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnGetMemberInfoSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnGetMemberInfoFailed(e);
            }
        }

        /// <summary>
        /// Processes the cluster get card reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterGetCardReply(ClusterGetCardPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterGetCardPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnGetCardSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnGetCardFailed(e);
            }
        }
        /// <summary>
        /// Processes the cluster get card batch reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterGetCardBatchReply(ClusterGetCardBatchPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterGetCardBatchPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnBatchGetCardSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnBatchGetCardFailed(e);
            }
        }

        /// <summary>
        /// Processes the cluster sub cluster op reply.
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <param name="outPacket">The out packet.</param>
        private void ProcessClusterSubClusterOpReply(ClusterSubClusterOpPacket outPacket, ClusterCommandReplyPacket inPacket)
        {
            var e = new QQEventArgs<ClusterSubClusterOpPacket, ClusterCommandReplyPacket>(outPacket, inPacket);
            if (inPacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
            {
                client.ClusterManager.OnGetDialogSubjectSuccessfully(e);
            }
            else
            {
                client.ClusterManager.OnGetDialogSubjectFailed(e);
            }
        }
        /**
     * 处理高级搜索的回复包
     *
     * @param in
     */
        private void ProcessAdvancedSearchReply(AdvancedSearchUserPacket outpacket, AdvancedSearchUserReplyPacket inpacket)
        {
            var e = new QQEventArgs<AdvancedSearchUserPacket, AdvancedSearchUserReplyPacket>(outpacket, inpacket);

            if (inpacket.ReplyCode == _08QQ.Reply_Search.QQ_REPLY_OK && !inpacket.Finished)
            {
                //log.debug("高级搜索成功");
                client.FriendManager.OnAdvancedSearchUserOK(e);
            }
            else if (inpacket.ReplyCode == _08QQ.Reply_Search.QQ_REPLY_ADVANCED_SEARCH_END || inpacket.Finished)
            {
                //log.debug("高级搜索完毕");
                client.FriendManager.OnAdvancedSearchUserEnd(e);
            }
            else
            {
                //log.debug("高级搜索返回未知回复码");
            }
        }

        /**
     * 处理用户属性回复包
     *
     * @param in
     */
        private void ProcessUserPropertyOpReply(UserPropertyOpPacket outpacket, UserPropertyOpReplyPacket inpacket)
        {
            var e = new QQEventArgs<UserPropertyOpPacket, UserPropertyOpReplyPacket>(outpacket, inpacket);
            client.PrivacyManager.OnGetPropertySuccessfully(e);
        }

        /**
     * 处理临时会话回复包
     *
     * @param in
     */
        private void ProcessTempSessionOpReply(TempSessionOpPacket outpacket, TempSessionOpReplyPacket inpacket)
        {
            var e = new QQEventArgs<TempSessionOpPacket, TempSessionOpReplyPacket>(outpacket, inpacket);
            switch (inpacket.ReplyCode)
            {
                case _08QQ.TempSessionOpReply.QQ_REPLY_OK:
                case _08QQ.TempSessionOpReply.QQ_REPLY_MAYBE_OFFLINE:
                    client.MessageManager.OnTempSessionSendSuccessfully(e);
                    break;
                default:
                    client.MessageManager.OnTempSessionSendFailed(e);
                    break;
            }
        }

        /**
     * 处理验证信息
     *
     * @param in
     */
        private void ProcessAuthInfoOpReply(_08AuthInfoOpPacket outpacket, _08AuthInfoOpReplyPacket inpacket)
        {
            var e = new QQEventArgs<_08AuthInfoOpPacket, _08AuthInfoOpReplyPacket>(outpacket, inpacket);
            switch (inpacket.SubCommand)
            {
                case _08QQ.SubCMD_Auth_Info.QQ_SUB_CMD_GET_AUTH_INFO:
                    //log.debug("用户验证信息已经被获取！");
                    //e = new _08QQEvent(packet);
                    switch (inpacket.SubSubCommand)
                    {
                        default:
                            user.AuthToken = inpacket.AuthInfo;
                            user.ImageUrl = (Utils.Util.GetString(inpacket.AuthInfo));
                            break;
                    }

                    break;
                //case _08QQ.SubCMD_Auth_Info.QQ_SUB_CMD_SUBMIT_AUTH_INFO_BY_VERTIFYCODE:
                //    //e = new _08QQEvent(packet);
                //    //user.setAuthToken(packet.authInfo);
                //    //e.type = packet.replyCode == _08QQ.QQ_REPLY_OK ? _08QQEvent.FRIEND_SUBMIT_AUTO_INFO_OK
                //    //        : _08QQEvent.FRIEND_SUBMIT_AUTO_INFO_FAIL;
                //    //client.fireQQEvent(e);
                //    break;
            }
            client.LoginManager.OnReceivedAuthInfo(e);
        }

        private void ProcessAuthQuestionOpReply(AuthQuestionOpPacket outpacket, AuthQuestionOpReplyPacket inpacket)
        {
            var e = new QQEventArgs<AuthQuestionOpPacket, AuthQuestionOpReplyPacket>(outpacket, inpacket);

            switch (inpacket.SubCommand)
            {
                case _08QQ.SubCMD_Auth_Question.QQ_SUB_CMD_GET_QUESTION:
                    if (inpacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
                    {
                        client.FriendManager.OnGetAuthQuestionSuccessfully(e);
                    }
                    else
                    {
                        client.FriendManager.OnGetAuthQuestionFailed(e);
                    }
                    break;
                case _08QQ.SubCMD_Auth_Question.QQ_SUB_CMD_ANSWER_QUESTION:
                    if (inpacket.ReplyCode == _08QQ.ReplyCode.QQ_REPLY_OK)
                    {
                        client.FriendManager.OnRightAnswer(e);
                    }
                    else
                    {
                        client.FriendManager.OnWrongAnswer(e);
                    }
                    break;
            }
        }
        #endregion

        public bool Accept(Packets._08InPacket inPacket)
        {
            return inPacket.GetFamily() == _08QQ.ProtocolFamily.QQ_PROTOCOL_FAMILY_BASIC;
        }

        /// <summary>判断包是否时登录前可以出现的包，有些包是在登录前可以处理的，如果不是，应该缓存起来等
        /// 到登录成功后再处理，不过但是在实际中观察发现，登录之前收到的东西基本没用，可以不管
        /// 	<remark>abu 2008-03-08 </remark>
        /// </summary>
        /// <param name="inPacket">The in packet.</param>
        /// <returns></returns>
        private bool IsPreloginPacket(_08InPacket inPacket)
        {
            switch (inPacket.Command)
            {
                case _08QQ.Command.QQ_CMD_LOGIN:
                case _08QQ.Command.QQ_CMD_TOUCH:
                case _08QQ.Command.QQ_CMD_LOGIN_TOKEN_1:
                case _08QQ.Command.QQ_CMD_LOGIN_TOKEN_2:
                case _08QQ.Command.QQ_CMD_CHECK_PASSWORD:
                case _08QQ.Command.QQ_CMD_FIRST_LOGIN:
                    return true;
                case _08QQ.Command.QQ_CMD_UNKNOWN:
                    return inPacket is ErrorPacket;
                default:
                    return false;
            }
        }
    }
}
